/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief Header for "Delayed Link" extension of the AP.
 * \author Antti Maula <antti.maula@tkk.fi>
 */
#ifndef _TCPHUB_DELAYEDLINK_H_
#define _TCPHUB_DELAYEDLINK_H_

#include "buffer.h"


/**
 * This structure defines information for one single frame.
 * 
 */
typedef struct _delayedFrameInfo {
  // Timing information
  long int received_time_s; ///< Received timestamp in seconds
  long int received_time_us; ///< Received timestamp in useconds
    
  // Data pointer information
  int data_size; ///< Amount of data in frame. Always from beginning of buffer.

} TDelayedFrameInfo;


/**
 * This structure contains information for storing Delayed packet information.
 * 
 *
 *
 */
typedef struct _delayedLinkInfo {
  // Parameters for delayed link
  int linkDelayMs; ///< Link delay in milliseconds

  // Array of individual frame info
  int frameInfoArraySize; ///< Number of elements in frame array
  TBuffer frameInfoArray; ///< TBuffer containing the element array

} TDelayedLinkInfo;





/**
 * Returns pointer to newly allocated and initialized LinkInfo entry.
 *
 * @param[in] aDelay_ms         Initial delay_ms to set for this entry.
 * @return                      Pointer to new allocated entry. Notice;
 *                              this must be destroyed with 'DestroyLinkInfoEntry'
 *                              when no longer required.
 */
TDelayedLinkInfo *delayedLinkCreateLinkInfoEntry(const int aDelay_ms);


/**
 * Destroys a previously created LinkInfo entry.
 *
 * @param[in] aLinkInfoEntry    Pointer to entry to destroy.
 */
void delayedLinkDestroyLinkInfoEntry(TDelayedLinkInfo *aLinkInfoEntry);


/**
 * Pushes a new frame to end of DelayedLink table. The entry is
 * timestamped when pushed.
 *
 * @param[in] aInfo             Pointer to info to read parameters from
 */
int delayedLinkPushFrame(TDelayedLinkInfo *aInfo, const int aSize);


/**
 * Pops out a frame from beginning of DelayedLink table.
 *
 * @param[in] aInfo             Pointer to info to read parameters from
 */
int delayedLinkPopFrame(TDelayedLinkInfo *aInfo);


/**
 * Returns a constant pointer to next Entry in the FrameInfoPtr array.
 * This may be used to inspect some parameters.
 *
 * @param[in] aInfo             Pointer to info to read parameters from
 * @return                      const pointer to first FrameInfo in the queue,
 *                              or NULL in case of queue empty.
 */
const TDelayedFrameInfo *delayedLinkGetNextFrameInfoPtr(const TDelayedLinkInfo *aInfo);


/**
 * This function is handy shortcut for higher level users. It returns the number
 * of bytes expired in the buffer. The caller can flush this amount of data from the buffer,
 * and then simply call the 'PopExpiredSize' method the clean out the entries.
 * 
 * @param[in] aInfo             Pointer to info to read parameters from
 * @return                      Number of bytes expired in buffer. If nothing
 *                              is yet expired, zero is returned. If the queue
 *                              is empty, zero is returned. In case of any error,
 *                              negative value is returned.
 */
int delayedLinkGetExpiredSize(const TDelayedLinkInfo *aInfo);


/**
 * Returns the time left (in ms) until next frame needs to be purged.
 * 
 * @param[in] aInfo             Pointer to info to read parameters from
 * @return                      Positive value in milliseconds before next
 *                              frame in queue is expired. If the next frame
 *                              is already expired, zero is returned. 
 *                              If the queue is empty, negative value is returned.
 *
 */
int delayedLinkGetTimeMsUntilNextExpiredFrame(const TDelayedLinkInfo *aInfo);


/**
 * This function will clean out the entries spanning over the given byte range.
 * NOTE: If the value is not equal to sum of frame sizes, the overflowing amount
 * is ignored and the entry is not removed. So, call this function ONLY with the
 * return value from the 'GetExpiredSize' method to avoid problems.
 * 
 * @param[in] aInfo             Pointer to info to read parameters from
 * @param[in] aSize             Number of bytes to pop. It can include multiple entries,
 *                              but entries must be included as a whole. (== The size 
 *                              must match the sum of n-entries.
 * @return                      On success, returns number of _elements_ removed, 
 *                              in case of error, returns negative value.
 */
int delayedLinkPopExpiredSize(TDelayedLinkInfo *aInfo, const int aSize);





#endif //_TCPHUB_DELAYEDLINK_H_
